import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.font_manager import FontProperties
from matplotlib import gridspec
from matplotlib import rcParams
rcParams['font.family'] = 'times new roman'

font = {'family' : 'times new roman',
        'weight' : 'normal',  
        'size'   : 15,  
        }

numHosts  = 10
numToRs   = 100
numCores  = 4
numOCSes  = 4
numDemands = 1
update_enable = True

flowsNum_a = 50
flowsNum_b = 50
flowSizes = [(100, 1000)]
groupSizes = [(3, 11)]    # 10 ~ 100

flow_num = 10000
flow_interval = 1000.0

workloads = ['hybird', 'multicast'] #[('hybird', 'unicast', 'multicast')]
scheduler = ['unicast', 'binomial', 'ring', 'eps', 'ocs', 'jcast']
#scheduler = ['eps', 'ocs', 'jcast']

iteration_a = 0
iteration_b = 10 # run 10 times

# -----------------------------------------------------------
y_unicast_fct 	= {} #hybrid, multicast
y_binominal_fct = {}
y_ring_fct 		= {}
y_eps_fct 		= {}
y_ocs_fct 		= {}
y_jcast_fct 	= {}

y_unicast_en 	= {} #hybrid, multicast
y_binominal_en 	= {}
y_ring_en 		= {}
y_eps_en 		= {}
y_ocs_en 		= {}
y_jcast_en	 	= {}

for i in xrange(iteration_a, iteration_b):

	y_unicast_fct[i] 	= [0, 0] #hybrid, multicast
	y_binominal_fct[i]  = [0, 0]
	y_ring_fct[i] 		= [0, 0]
	y_eps_fct[i] 		= [0, 0]
	y_ocs_fct[i] 		= [0, 0]
	y_jcast_fct[i]  	= [0, 0]

	y_unicast_en[i] 	= [0, 0] #hybrid, multicast
	y_binominal_en[i] 	= [0, 0]
	y_ring_en[i] 		= [0, 0]
	y_eps_en[i] 		= [0, 0]
	y_ocs_en[i] 		= [0, 0]
	y_jcast_en[i]	 	= [0, 0]

	for (groupSize_a, groupSize_b) in groupSizes: # different groupSize
		print (groupSize_a, groupSize_b)
		for (flowSize_a, flowSize_b) in flowSizes: # different flowSize
			print (flowSize_a, flowSize_b)
			for workload in workloads:
				for sched in scheduler:
					mflowsFileName = "%sCore_%sOCS_%sToR_%sHost_%sDemand_%sFlows_%s%sSize_%s%sGroup_%s_%s_%s_%s.txt"\
									%(numCores, numOCSes, numToRs, numHosts, numDemands, flowsNum_b, int(flowSize_a), int(flowSize_b), int(groupSize_a), int(groupSize_b), i,\
									sched, update_enable, workload)
					#print mflowsFileName

					with open(mflowsFileName, 'r') as f:
						for line in f.readlines():
							split = line.split()
							if workload == 'hybird':
								if sched == 'unicast':
									y_unicast_fct[i][0] += float(split[5])
									y_unicast_en[i][0] += float(split[-1])
								elif sched == 'binomial':
									y_binominal_fct[i][0] += float(split[5])
									y_binominal_en[i][0] += float(split[-1])
								elif sched == 'ring':
									y_ring_fct[i][0] += float(split[5])
									y_ring_en[i][0] += float(split[-1])
								elif sched == 'eps':
									y_eps_fct[i][0] += float(split[5])
									y_eps_en[i][0] += float(split[-1])
								elif sched == 'ocs':
									y_ocs_fct[i][0] += float(split[5])
									y_ocs_en[i][0] += float(split[-1])
								elif sched == 'jcast':
									y_jcast_fct[i][0] += float(split[5])
									y_jcast_en[i][0] += float(split[-1])
							else:
								if sched == 'unicast':
									y_unicast_fct[i][1] += float(split[5])
									y_unicast_en[i][1] += float(split[-1])
								elif sched == 'binomial':
									y_binominal_fct[i][1] += float(split[5])
									y_binominal_en[i][1] += float(split[-1])
								elif sched == 'ring':
									y_ring_fct[i][1] += float(split[5])
									y_ring_en[i][1] += float(split[-1])
								elif sched == 'eps':
									y_eps_fct[i][1] += float(split[5])
									y_eps_en[i][1] += float(split[-1])
								elif sched == 'ocs':
									y_ocs_fct[i][1] += float(split[5])
									y_ocs_en[i][1] += float(split[-1])
								elif sched == 'jcast':
									y_jcast_fct[i][1] += float(split[5])
									y_jcast_en[i][1] += float(split[-1])

'''
print y_unicast_fct
print y_binominal_fct
print y_ring_fct
print y_eps_fct
print y_ocs_fct
print y_jcast_fct

print y_unicast_en
print y_binominal_en
print y_ring_en
print y_eps_en
print y_ocs_en
print y_jcast_en
'''

y_unicast_fct_mean 		= np.array(y_unicast_fct.values()).mean(axis=0)
y_binominal_fct_mean 	= np.array(y_binominal_fct.values()).mean(axis=0)
y_ring_fct_mean 		= np.array(y_ring_fct.values()).mean(axis=0)
y_eps_fct_mean 			= np.array(y_eps_fct.values()).mean(axis=0)
y_ocs_fct_mean 			= np.array(y_ocs_fct.values()).mean(axis=0)
y_jcast_fct_mean 		= np.array(y_jcast_fct.values()).mean(axis=0)

y_unicast_en_mean 		= np.array(y_unicast_en.values()).mean(axis=0)
y_binominal_en_mean 	= np.array(y_binominal_en.values()).mean(axis=0)
y_ring_en_mean 			= np.array(y_ring_en.values()).mean(axis=0)
y_eps_en_mean 			= np.array(y_eps_en.values()).mean(axis=0)
y_ocs_en_mean 			= np.array(y_ocs_en.values()).mean(axis=0)
y_jcast_en_mean	 		= np.array(y_jcast_en.values()).mean(axis=0)

y_unicast_fct_err 		= np.array(y_unicast_fct.values()).std(axis=0)
y_binominal_fct_err 	= np.array(y_binominal_fct.values()).std(axis=0)
y_ring_fct_err	 		= np.array(y_ring_fct.values()).std(axis=0)
y_eps_fct_err 			= np.array(y_eps_fct.values()).std(axis=0)
y_ocs_fct_err 			= np.array(y_ocs_fct.values()).std(axis=0)
y_jcast_fct_err 		= np.array(y_jcast_fct.values()).std(axis=0)

y_unicast_en_err 		= np.array(y_unicast_en.values()).std(axis=0)
y_binominal_en_err	 	= np.array(y_binominal_en.values()).std(axis=0)
y_ring_en_err 			= np.array(y_ring_en.values()).std(axis=0)
y_eps_en_err 			= np.array(y_eps_en.values()).std(axis=0)
y_ocs_en_err 			= np.array(y_ocs_en.values()).std(axis=0)
y_jcast_en_err	 		= np.array(y_jcast_en.values()).std(axis=0)

print y_jcast_fct_mean, y_ocs_fct_mean, y_eps_fct_mean
print 'fct'
print 'jcast_to_ocs', (y_ocs_fct_mean-y_jcast_fct_mean)/y_ocs_fct_mean
print 'jcast_to_eps', (y_eps_fct_mean-y_jcast_fct_mean)/y_eps_fct_mean
print 'jcast_to_ring', (y_ring_fct_mean-y_jcast_fct_mean)/y_ring_fct_mean
print 'jcast_to_binomal', (y_binominal_fct_mean-y_jcast_fct_mean)/y_binominal_fct_mean
print 'jcast_to_unicast', (y_unicast_fct_mean-y_jcast_fct_mean)/y_unicast_fct_mean

'''
jcast_to_ocs [ 0.31684565  0.31777685]
jcast_to_eps [ 0.27730722  0.18766785]
jcast_to_ring [ 0.45933606  0.45047163]
jcast_to_binomal [ 0.64403959  0.58809124]
jcast_to_unicast [ 0.81074821  0.82274377]
'''

print y_jcast_en_mean, y_ocs_en_mean, y_eps_en_mean
print 'energy'
print 'jcast_to_ocs', (y_ocs_en_mean-y_jcast_en_mean)/y_ocs_en_mean
print 'jcast_to_eps', (y_eps_en_mean-y_jcast_en_mean)/y_eps_en_mean
print 'jcast_to_ring', (y_ring_en_mean-y_jcast_en_mean)/y_ring_en_mean
print 'jcast_to_binomal', (y_binominal_en_mean-y_jcast_en_mean)/y_binominal_en_mean
print 'jcast_to_unicast', (y_unicast_en_mean-y_jcast_en_mean)/y_unicast_en_mean

'''
energy
jcast_to_ocs [-0.01953439 -0.02199341]
jcast_to_eps [ 0.36213275  0.35677429]
jcast_to_ring [ 0.6720792   0.67126407]
jcast_to_binomal [ 0.63630509  0.63533277]
jcast_to_unicast [ 0.68714436  0.68686631]
'''

ind = np.arange(2)  # the x locations for the groups
labels = ('Multicast & Unicast', 'Multicast')
width = 0.1 # the width of the bars
offset = 0.14

fig = plt.figure(figsize=(5.8,3.5))
ax = plt.axes()

fig_type = 'fct' # 'energy', 'fct'
if fig_type == 'fct':
	l_jcast     = plt.bar(ind+width*0+offset, y_jcast_fct_mean, yerr=y_jcast_fct_err,  width=width, edgecolor='black', color='darkkhaki',  zorder=0)
	l_ocs       = plt.bar(ind+width*1+offset, y_ocs_fct_mean, yerr=y_ocs_fct_err, width=width, edgecolor='black', color='indianred',  zorder=0)
	l_eps       = plt.bar(ind+width*2+offset, y_eps_fct_mean, yerr=y_eps_fct_err, width=width, edgecolor='black', color='cornflowerblue', hatch="-", zorder=0)
	l_ring      = plt.bar(ind+width*3+offset, y_ring_fct_mean, yerr=y_ring_fct_err, width=width, edgecolor='black', color='thistle', hatch="/", zorder=0)
	l_binominal = plt.bar(ind+width*4+offset, y_binominal_fct_mean, yerr=y_binominal_fct_err, width=width, edgecolor='black', color='darkseagreen',hatch="\\", zorder=0)
	l_unicast   = plt.bar(ind+width*5+offset, y_unicast_fct_mean, yerr=y_unicast_fct_err, width=width, edgecolor='black', color='darkgrey',zorder=0)

	plt.ylabel('Multicast Flow Completion Time (s)', fontdict=font)
	plt.yticks(fontproperties = 'times new roman')
	plt.xticks(ind+width*3+offset, labels, fontproperties="times new roman", fontsize=14)
	plt.yscale('log')
	plt.subplots_adjust(bottom=0.10, top=0.95, left=0.15, right=0.95)
	plt.legend((l_jcast,l_ocs,l_eps,l_ring,l_binominal,l_unicast), \
	            ('iCast','OCS','EPS','Ring','Binomial Tree','Unicast'), ncol=3, loc='upper center', prop={'family':'times new roman','size': 12})
	ax.yaxis.grid(zorder=0, ls='--')
	#plt.savefig('0_Simulation_FCT.pdf')
	plt.show()
else:
	l_jcast     = plt.bar(ind+width*0+offset, y_jcast_en_mean, yerr=y_jcast_en_err, width=width, edgecolor='black',color='darkkhaki', zorder=0)
	l_ocs       = plt.bar(ind+width*1+offset, y_ocs_en_mean, yerr=y_ocs_en_err, width=width, edgecolor='black',color='indianred',  zorder=0)
	l_eps       = plt.bar(ind+width*2+offset, y_eps_en_mean, yerr=y_eps_en_err, width=width, edgecolor='black',color='cornflowerblue', hatch="-",  zorder=0)
	l_ring      = plt.bar(ind+width*3+offset, y_ring_en_mean, yerr=y_ring_en_err, width=width, edgecolor='black',color='thistle', hatch="/", zorder=0)
	l_binominal = plt.bar(ind+width*4+offset, y_binominal_en_mean, yerr=y_binominal_en_err, width=width, edgecolor='black',color='darkseagreen', hatch="\\", zorder=0)
	l_unicast   = plt.bar(ind+width*5+offset, y_unicast_en_mean, yerr=y_unicast_en_err, width=width, edgecolor='black',color='darkgrey',zorder=0)

	plt.ylabel('Energy Consumption', fontdict=font)
	plt.yticks(fontproperties = 'times new roman')
	plt.xticks(ind+width*3+offset, labels, fontproperties="times new roman", fontsize=14)
	plt.yscale('log')
	#plt.ylim(0, 1.6e15)
	plt.subplots_adjust(bottom=0.10, top=0.95, left=0.16, right=0.95)
	plt.legend((l_jcast,l_ocs,l_eps,l_ring,l_binominal,l_unicast), \
	            ('iCast','OCS','EPS','Ring','Binomial Tree','Unicast'), ncol=3, loc='upper center', prop={'family':'times new roman','size': 12})

	ax.yaxis.grid(zorder=0, ls='--')
	plt.savefig('0_Simulation_Energy.pdf')
	plt.show()

